package day7.zy5;

public class Test {
//    一、NIO
//
//    在介绍NIO编程之前，我们首先需要澄清一个概念：NIO到底是什么的简称？有人称之为New I/O，因为它相对于之前的I/O类库是新增的，所以被称为New I/O，这是它的官方叫法。但是，由于之前老的I/O类库是阻塞I/O，New I/O类库的目标就是要让Java支持非阻塞I/O，所以，更多的人喜欢称之为非阻塞I/O（Non-block I/O），由于非阻塞I/O更能够体现NIO的特点，所以我们这里使用NIO表示非阻塞I/O。
//
//    与Socket类和ServerSocket类相对应，NIO也提供了SocketChannel和ServerSocketChannel两种不同的套接字通道实现。这两种新增的通道都支持阻塞和非阻塞两种模式。阻塞模式使用非常简单，但是性能和可靠性都不好，非阻塞模式则正好相反。开发人员一般可以根据自己的需要来选择合适的模式，一般来说，低负载，低并发的应用程序可以选择同步阻塞I/O以降低编程复杂度，但是对于高负载，高并发的网络应用，需要使用NIO的非阻塞模式进行开发。
//
//    NIO类库简介
//
//1、缓冲区Buffer
//
//    我们首先介绍缓冲区（Buffer）的概念，Buffer是一个对象，它包含一些要写入或者要读出的数据。在NIO类库中加入Buffer对象，体现了新库与原I/O的一个重要区别。在面向流的I/O中，可以将数据直接写入或者将数据直接读到Stream对象中。
//
//    在NIO库中，所有数据都是用缓冲区处理的。在读取数据时，它是直接读到缓冲区中的；在写入数据时，写入到缓冲区中。任何时候访问NIO中的数据，都是通过缓冲区进行操作。
//
//    缓冲区实质上是一个数组。通常它是一个字节数组（ByteBuffer），也可以使用其他种类的数组。但是一个缓冲区不仅仅是一个数组，缓冲区提供了对数据的结构化访问以及维护读写位置（limit）等信息。
//
//    最常用的缓冲区是ByteBuffer，一个ByteBuffer提供了一组功能用于操作byte数组。除了ByteBuffer，还有其他的一些缓冲区，事实上，每一种Java基本类型（除了Boolean类型）都对应有一种缓冲区，具体如下：
//
//    ByteBuffer：字节缓冲区
//    CharBuffer：字符缓冲区
//    ShortBuffer：短整型缓冲区
//    IntBuffer：整型缓冲区
//    LongBuffer：长整型缓冲区
//    FloatBuffer：浮点型缓冲区
//    DoubleBuffer：双精度浮点型缓冲区
//    缓冲区的继承关系如下图所示：
//
//    每一个Buffer类都是Buffer接口的一个子实例。除了ByteBuffer，每一个Buffer类都有完全一样的操作，只是它们所处理的数据类型不一样。因为大多数标准I/O操作都使用ByteBuffer，所以它除了具有一般缓冲区的操作之外还提供一些特有的操作，方便网络读写。
//
//            2、通道Channel
//
//    Channel是一个通道，可以通过它读取和写入数据，它就像输水管道一样，网络数据通过Channel读取和写入。通道与流的不同之处在于通道是双向的，流只是在一个方向上移动（一个流必须是InputStream 或者 OutputStream的子类），而且通道可以用于读，写或者同时用于读写。
//
//    因为Channel是全双工的，所以它可以比流更好地映射底层操作系统的API。特别是在UNIX网络编程模型中，底层操作系统的通道都是全双工的，同时支持读写操作。
//
//    Channel的集成关系如下图所示：
//
//
//    自顶向下看， 前三层主要是Channel接口，用于定义它的功能，后面是一些具体的功能类（抽象类）。从类图可以看出，实际上Channel可以分为两大类：分别是用于网络读写的SelectableChannel和用于文件操作的FileChannel。
//
//            3、多路复用器Selector
//
//    多路复用器Selector，它是Java NIO编程的基础，熟练地掌握Selector对于掌握NIO编程至关重要。多路复用器提供选择已经就绪的任务的能力。简单来讲， Selector会不断地轮询注册在其上的Channel，如果某个Channel上面有新的TCP连接接入，读和写事件，这个Channel就处于就绪状态，会被Selector轮询出来，然后通过SelectionKey可以获取就绪Channel的集合，进行后续的I/O操作 。
//
//    一个多路复用器Selector可以同时轮询多个Channel，由于JDK使用了epoll()代替传统的select实现，所以它并没有最大连接句柄1024/2048的限制。这也就意味着只需要一个线程负责Selector的轮询，就可以接入成千上万的客户端，这确实是个非常巨大的进步。
//
//            4、NIO服务端序列图
//
//
//    尽管NIO编程难度确实比同步阻塞BIO大很多，但是我们要考虑到它的优点：
//
//    客户端发起的连接操作是异步的，可以通过在多路复用器注册OP_CONNECT等后续结果，不需要像之前的客户端那样被同步阻塞。
//    SocketChannel的读写操作都是异步的，如果没有可读写的数据它不会同步等待，直接返回，这样IO通信线程就可以处理其它的链路，不需要同步等待这个链路可用。
//    线程模型的优化：由于JDK的Selector在Linux等主流操作系统上通过epoll实现，它没有连接句柄数的限制(只受限于操作系统的最大句柄数或者对单个进程的句柄限制)，这意味着一个Selector线程可以同时处理成千上万个客户端连接，而且性能不会随着客户端的增加而线性下降，因此，它非常适合做高性能、高负载的网络服务器。
//    二、AIO
//
//    JDK1.7升级了NIO类库，升级后的NIO类库被称为NIO2.0。也就是我们要介绍的AIO。NIO2.0引入了新的异步通道的概念，并提供了异步文件通道和异步套接字通道的实现。异步通道提供两种方式获取操作结果。
//
//    通过Java.util.concurrent.Future类来表示异步操作的结果；
//    在执行异步操作的时候传入一个Java.nio.channels.
//            CompletionHandler接口的实现类作为操作完成的回调。
//    NIO2.0的异步套接字通道是真正的异步非阻塞IO，它对应UNIX网络编程中的事件驱动IO(AIO)，它不需要通过多路复用器(Selector)对注册的通道进行轮询操作即可实现异步读写，从而简化了NIO的编程模型。
//
//    我们可以得出结论：异步Socket Channel是被动执行对象，我们不需要像NIO编程那样创建一个独立的IO线程来处理读写操作。对于AsynchronousServerSocketChannel和AsynchronousSocketChannel，它们都由JDK底层的线程池负责回调并驱动读写操作。正因为如此，基于NIO2.0新的异步非阻塞Channel进行编程比NIO编程更为简单。
}
